package com.cysyz.module.permission.stateless.realm;


import com.cysyz.module.permission.stateless.CvsPermission;
import com.cysyz.module.permission.stateless.exception.SignCheckException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;

public class StatelessRealm extends AuthorizingRealm {

    @Resource
    private PermissionService permissionService;

    @Override
    public boolean supports(AuthenticationToken token) {
        //仅支持StatelessToken类型的Token
        return token instanceof StatelessToken;
    }
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //根据用户名查找角色，请根据需求实现
        String appKey = (String) principals.getPrimaryPrincipal();

        SimpleAuthorizationInfo authorizationInfo =  new SimpleAuthorizationInfo();
        authorizationInfo.addObjectPermission(new CvsPermission(permissionService.findAllPermissions(appKey)));
        return authorizationInfo;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        StatelessToken statelessToken = (StatelessToken) token;

        String appKey = statelessToken.getAppKey();

        String partnerCode = statelessToken.getPartnerCode();

        if (!permissionService.isBizIdAndKeyBelongSamePerson(partnerCode, appKey)) {
            throw new AuthenticationException("业务标识与app_key不属于同一个用户");
        }

        checkAppkeyExists(appKey);

        String appSecret = getSecret(appKey);//根据Key获取密钥

        if (appSecret == null) {
            throw new RuntimeException("状态异常, 找不到key对应的secret");
        }

        String clientDigest = statelessToken.getClientDigest();

        if(!permissionService.checkSign(statelessToken.getParams(), clientDigest, appSecret)){
            throw new SignCheckException("签名校验失败");
        }


        return new SimpleAuthenticationInfo(
                appKey,
                clientDigest,
                getName());
    }

    private void checkAppkeyExists(String appKey) {
        if(!permissionService.isAppKeyExist(appKey)) {
            throw new UnknownAccountException("不存在的app_key");
        }
    }

    private String getSecret(String appKey) {
        return permissionService.getSecret(appKey);
    }
}
